package com.habdqn.studentmanager.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.github.pagehelper.PageInfo;
import com.github.xiaofan1519.verify.core.Verify;
import com.github.xiaofan1519.verify.exception.VerifyException;
import com.habdqn.studentmanager.bean.Classes;
import com.habdqn.studentmanager.bean.Student;
import com.habdqn.studentmanager.bean.Teacher;
import com.habdqn.studentmanager.bean.ajax.Page;
import com.habdqn.studentmanager.bean.ajax.Request;
import com.habdqn.studentmanager.bean.ajax.Response;
import com.habdqn.studentmanager.bean.condition.BigDecimalCondition;
import com.habdqn.studentmanager.bean.condition.DateCondition;
import com.habdqn.studentmanager.bean.score.ClassScore;
import com.habdqn.studentmanager.bean.score.Score;
import com.habdqn.studentmanager.bean.score.StudentPoint;
import com.habdqn.studentmanager.bean.score.StudentScore;
import com.habdqn.studentmanager.bean.score.req.ClassScoreCondition;
import com.habdqn.studentmanager.bean.score.req.ScoreCondition;
import com.habdqn.studentmanager.constant.Constant;
import com.habdqn.studentmanager.constant.ErrorCode;
import com.habdqn.studentmanager.exception.StudentException;
import com.habdqn.studentmanager.service.ScoreService;
import com.habdqn.studentmanager.util.DateUtil;
import com.habdqn.studentmanager.util.ProjectUtil;

@Controller
@RequestMapping("/score")
public class ScoreController extends BaseController {

	private static final Logger logger = LoggerFactory.getLogger(ScoreController.class);

	@Resource
	private ScoreService scoreService;

	/**
	 * 
	 * @return
	 */
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String toList() {

		return "score/list";
	}

	@RequestMapping(value = "/list", method = RequestMethod.POST)
	@ResponseBody
	public Response list(@RequestBody Request<ScoreCondition> req) {

		logger.debug("req:{}", req);

		try {
			ScoreCondition condition = req.getCondition();

			Verify.verifyNull(req);
			Verify.verifyNull(condition);

			Page page = getPage(req);

			Score bean = new Score();
			Student stu = new Student();
			stu.setId(condition.getStudentId());
			Classes classes = new Classes();
			classes.setName(condition.getClassName());
			stu.setClasses(classes);
			bean.setStudent(stu);

			DateCondition dateCondition = new DateCondition();
			dateCondition.setStartDate(condition.getStartDate());
			dateCondition.setEndDate(condition.getEndDate());

			BigDecimalCondition pointCondition = new BigDecimalCondition();
			pointCondition.setMin(condition.getMinPoint());
			pointCondition.setMax(condition.getMaxPoint());

			PageInfo<Score> pageInfo = scoreService.findList(bean, page, dateCondition, pointCondition);
			return buildRsp(pageInfo);
		}
		catch (VerifyException e) {
			logger.debug("请求参数为空");
			return buildRsp(ErrorCode.Invalid_Argument, "请求参数为空");
		}
		catch (StudentException e) {
			return buildRsp(ErrorCode.System_Error, e.getMessage());
		}
	}

	@RequestMapping(value = "/{id}/info", method = RequestMethod.GET)
	@ResponseBody
	public Response info(@PathVariable Integer id) {
		Score bean = new Score();
		try {
			Verify.verifyNull(id);
			bean.setId(id);
			bean = scoreService.find(bean);
		}
		catch (VerifyException e) {
			logger.error("成绩id为空", e);
			return buildRsp(ErrorCode.Invalid_Argument, "系统错误，请联系管理员");
		}
		catch (StudentException e) {
			logger.error(e.getMessage(), e);
			return buildRsp(ErrorCode.System_Error, e);
		}
		logger.debug("{}的成绩信息{}", id, bean);
		return buildRsp(bean);
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	@ResponseBody
	public Response add(@RequestBody Score score) {
		try {
			validateScore(score);
			scoreService.add(score);
		}
		catch (VerifyException e) {
			logger.error(e.getMessage());
			return buildRsp(ErrorCode.Invalid_Argument, e.getMessage());
		}
		catch (StudentException e) {
			logger.error(e.getMessage());
			return buildRsp(ErrorCode.System_Error, e);
		}
		logger.debug("添加成功，成绩信息：{}", score);
		return buildRsp();
	}

	/**
	 * 
	 * @param score
	 */
	private void validateScore(Score score) {
		Verify.verifyNull(score);
		// Verify.verifyNull(score.getId());
		Verify.verifyNull(score.getStudent());
		Verify.verifyEmpty(score.getStudent().getId());
		Verify.verifyNull(score.getDate());
		Verify.verifyNull(score.getType());
		Verify.verifyNull(score.getType().getValue());
		Verify.verifyNull(score.getPattern());
		Verify.verifyNull(score.getPattern().getValue());
		Verify.verifyNull(score.getPoint());
		Verify.verifyNull(score.getPassScore());
		Verify.verifyNull(score.getTotalScore());
		// Verify.verifyNull(score.getTeacher());
		// Verify.verifyNull(score.getTeacher().getId());
	}

	@RequestMapping(value = "/edit", method = RequestMethod.POST)
	@ResponseBody
	public Response edit(@RequestBody Score score) {
		Teacher teacher = (Teacher)ProjectUtil.getSessionAttr(Constant.CURRENT_TEACHER);
		score.setTeacher(teacher);
		try {
			Verify.verifyNull(score.getId());
			validateScore(score);
			scoreService.update(score);
		}
		catch (VerifyException e) {
			logger.error(e.getMessage());
			return buildRsp(ErrorCode.Invalid_Argument, e.getMessage());
		}
		catch (StudentException e) {
			logger.error(e.getMessage());
			return buildRsp(ErrorCode.System_Error, e.getMessage());
		}
		logger.debug("成功修改编号：{}的成绩信息", score.getId());
		return buildRsp();
	}

	@RequestMapping(value = "/{id}/del", method = RequestMethod.GET)
	@ResponseBody
	public Response del(@PathVariable Integer id) {
		Score bean = new Score();
		try {
			Verify.verifyNull(id);
			bean.setId(id);
			scoreService.delete(bean);
		}
		catch (VerifyException e) {
			logger.error(e.getMessage());
			return buildRsp(ErrorCode.Invalid_Argument, e.getMessage());
		}catch(StudentException e){
			logger.error(e.getMessage());
			return buildRsp(ErrorCode.System_Error, e.getMessage());
		}
		logger.debug("删除编号为：{}的成绩信息",id);
		return buildRsp();
	}
	
	/**
	 * 学生成绩图表展示页面
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/student/{id}/dashboard", method = RequestMethod.GET)
	public String toStudentDashBoard(@PathVariable String id, Model model) {
	    
	    try {
	        Verify.verifyEmpty(id);
	        Student bean = new Student();
	        bean.setId(id);
	        StudentScore studentScore = scoreService.getStudentDashBoard(bean);
	        addAttr(model, "student", studentScore.getStudent());
	        addAttr(model, "items", studentScore.getScores());
	        addAttr(model, "passRate", studentScore.getPassRate());
	        addAttr(model, "topScores", studentScore.getTopScores());
	    }
	    catch (VerifyException e) {
            return setErrMsg(model, "参数非法");
        }
	    catch (StudentException e) {
	        return setErrMsg(model, e);
        }
	    
	    return "score/student";
	}
	
	/**
     * 班级学生成绩图表展示页面
     * @param id
     * @return
     */
    @RequestMapping(value = "/class/{id}/dashboard", method = RequestMethod.GET)
    public String toClassDashBoard(@PathVariable String id, Model model) {
        
        try {
            logger.debug("className:{}", id);
            Verify.verifyEmpty(id);
            Classes classes = new Classes();
            classes.setName(id);
            List<ClassScore> trends = scoreService.findClassScoreTrend(classes);
            List<StudentPoint> sutdents = scoreService.findStudentScoreByClass(classes);
            
            // 计算整体及格率
            Float passRate = new Float(0);
            for (StudentPoint studentPoint : sutdents) {
                Float point = studentPoint.getPassRate();
                if (null == point) {
                    continue;
                }
                
                passRate += point;
            }
            passRate = passRate / sutdents.size();
            
            addAttr(model, "trends", trends);
            addAttr(model, "className", id);
            addAttr(model, "sutdents", sutdents);
            addAttr(model, "passRate", passRate);
        }
        catch (VerifyException e) {
            return setErrMsg(model, "参数非法");
        }
        catch (StudentException e) {
            return setErrMsg(model, e);
        }
        
        return "score/class";
    }
    
    /**
     * 导出
     */
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public String export(ScoreCondition condition, HttpServletResponse rsp, Model model) {
        
        Score bean = null;
        DateCondition dateCondition = null;
        BigDecimalCondition pointCondition = null;
        if (null != condition) {
            bean = new Score();
            Student stu = new Student();
            stu.setId(condition.getStudentId());
            Classes classes = new Classes();
            classes.setName(condition.getClassName());
            stu.setClasses(classes);
            bean.setStudent(stu);

            dateCondition = new DateCondition();
            dateCondition.setStartDate(condition.getStartDate());
            dateCondition.setEndDate(condition.getEndDate());

            pointCondition = new BigDecimalCondition();
            pointCondition.setMin(pointCondition.getMin());
            pointCondition.setMax(pointCondition.getMax());
        }
        
        try {
            String fileName = DateUtil.format(DateUtil.now(DateUtil.CHINA_TIMEZONE), DateUtil.FormatStr14) + ".xlsx";
            OutputStream out = setDownLoadModel(rsp, fileName);
            scoreService.export(bean, dateCondition, pointCondition, out);
        }
        catch (StudentException e) {
            return setErrMsg(model, e);
        }
        
        return null;
    }
    
    /**
     * 转发到导入页面
     * @return
     */
    @RequestMapping(value = "/import", method = RequestMethod.GET)
    public String toImport() {
        
        return "score/import";
    }
    
    /**
     * 批量导入学生成绩
     * @return
     */
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    @ResponseBody
    public Response importScore(@RequestParam("file") CommonsMultipartFile file) {
        
        try {
            InputStream is = file.getInputStream();
            scoreService.importScore(is);
            return buildRsp();
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
        catch (IOException e) {
            logger.error("打开上传文件失败", e);
            return buildRsp(ErrorCode.System_Error, "打开上传文件失败");
        }
    }
    
    @RequestMapping(value = "/class/list", method = RequestMethod.GET)
    public String toClassList() {
        
        return "score/classList";
    }
    
    @RequestMapping(value = "/class/list", method = RequestMethod.POST)
    @ResponseBody
    public Response getClassList(@RequestBody Request<ClassScoreCondition> req) {
        
        try {
            Verify.verifyNull(req);
            
            ClassScoreCondition condition = req.getCondition();
            return buildRsp(scoreService.findClassScoreList(condition, req.getPage()));
        }
        catch (StudentException e) {
            return buildRsp(ErrorCode.System_Error, e);
        }
    }
}
